interface Command {
    execute(): void
    undo(): void
}

class Receiver {
    public actionOn(): void {
        console.log("命令接收者，开启了某个动作");
    }

    public actionOff(): void {
        console.log("命令接收者，关闭了某个动作");
    }
}

//开启命令
class ConcreateCommandOn implements Command {
    private receiver: Receiver

    constructor(receiver: Receiver) {
        this.receiver = receiver
    }

    //命令执行
    execute(): void {
        this.receiver.actionOn()
    }
    //撤销命令
    undo(): void {
        this.receiver.actionOff()
    }

}

//关闭命令
class ConcreateCommandOff implements Command {
    private receiver: Receiver
    constructor(receiver: Receiver) {
        this.receiver = receiver
    }
    //执行命令的方法
    execute(): void {
        this.receiver.actionOff()
    }
    //撤销命令的方法
    undo(): void {
        console.log("撤销命令");
        this.receiver.actionOff()
    }
}

//空命令，可以用来省去命令判空操作
class NullCommond implements Command {
    execute(): void {

    }
    undo(): void {

    }
}

//命令调用者
class Invoker {
    private onCommandList: Array<Command>
    private offCommandList: Array<Command>
    private undoCommand: Command

    constructor() {
        this.undoCommand = new NullCommond()
        this.onCommandList = new Array()
        this.offCommandList = new Array()
    }

    public setCommand(index: number, onCommand: Command, offCommand: Command): void {
        //将命令插入到数组对应索引位置
        this.onCommandList.splice(index - 1, 0, onCommand)
        this.offCommandList.splice(index - 1, 0, offCommand)
    }

    //命令开启
    public on(index: number): void {
        this.onCommandList[index].execute()
        //更新撤销操作所对应的命令
        this.undoCommand = this.onCommandList[index]
    }

    //命令关闭
    public off(index: number): void {
        this.offCommandList[index].execute()
        //更新撤销操作所对应的命令
        this.undoCommand = this.offCommandList[index]
    }

    //撤销命令
    public undo(): void {
        this.undoCommand.undo()
    }
}

const CommandTest = (): void => {
    //创建命令接收者
    const receiver: Receiver = new Receiver()

    //创建命令
    const commandOn: Command = new ConcreateCommandOn(receiver)
    const commandOff: Command = new ConcreateCommandOff(receiver)

    //创建调用者
    const invoker: Invoker = new Invoker()
    //设置命令
    invoker.setCommand(0,commandOn,commandOff)

    invoker.on(0)
    invoker.off(0)
    invoker.undo()
}

CommandTest()